From 6a329a59de41a0b47b42d4db57b7ed9ec14811e5 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Thu, 24 Feb 2005 11:11:57 +0000 Subject: [PATCH] bitkeeper revision 1.1236.1.16 (421db67dL0mXatHebAtt9KpMqkCIBQ) More FPU fixes. Extend taskswitch hypercall to allow TS bit to be cleared as well as set. --- extras/mini-os/h/hypervisor.h | 10 ++++- .../arch/xen/kernel/process.c | 2 +- .../include/asm-xen/system.h | 2 +- .../arch/xen/i386/kernel/process.c | 2 +- .../arch/xen/i386/kernel/traps.c | 8 ---- .../include/asm-xen/asm-i386/system.h | 5 +-- .../include/asm-xen/hypervisor.h | 8 +++- .../sys/arch/xen/i386/machdep.c | 4 +- .../sys/arch/xen/include/hypervisor.h | 8 +++- xen/arch/x86/traps.c | 43 +++++++++---------- 10 files changed, 48 insertions(+), 44 deletions(-) diff --git a/extras/mini-os/h/hypervisor.h b/extras/mini-os/h/hypervisor.h index fee36d5b9c..e364253757 100644 --- a/extras/mini-os/h/hypervisor.h +++ b/extras/mini-os/h/hypervisor.h @@ -126,12 +126,18 @@ static __inline__ int HYPERVISOR_set_callbacks( } #endif -static __inline__ int HYPERVISOR_fpu_taskswitch(void) +static __inline__ int +HYPERVISOR_fpu_taskswitch( + int set) { int ret; + unsigned long ign; + __asm__ __volatile__ ( TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_fpu_taskswitch) : "memory" ); + : "=a" (ret), "=b" (ign) + : "0" (__HYPERVISOR_fpu_taskswitch), "1" (set) + : "memory" ); return ret; } diff --git a/linux-2.4.29-xen-sparse/arch/xen/kernel/process.c b/linux-2.4.29-xen-sparse/arch/xen/kernel/process.c index ad7e82dc79..905b51c113 100644 --- a/linux-2.4.29-xen-sparse/arch/xen/kernel/process.c +++ b/linux-2.4.29-xen-sparse/arch/xen/kernel/process.c @@ -334,7 +334,7 @@ void fastcall __switch_to(struct task_struct *prev_p, struct task_struct *next_p asm volatile( "fnsave %0 ; fwait" : "=m" (prev_p->thread.i387.fsave) ); prev_p->flags &= ~PF_USEDFPU; - queue_multicall0(__HYPERVISOR_fpu_taskswitch); + queue_multicall1(__HYPERVISOR_fpu_taskswitch, 1); } queue_multicall2(__HYPERVISOR_stack_switch, __KERNEL_DS, next->esp0); diff --git a/linux-2.4.29-xen-sparse/include/asm-xen/system.h b/linux-2.4.29-xen-sparse/include/asm-xen/system.h index 9be6e291fe..fd9faf34cb 100644 --- a/linux-2.4.29-xen-sparse/include/asm-xen/system.h +++ b/linux-2.4.29-xen-sparse/include/asm-xen/system.h @@ -109,7 +109,7 @@ static inline unsigned long _get_base(char * addr) /* NB. 'clts' is done for us by Xen during virtual trap. */ #define clts() ((void)0) -#define stts() (HYPERVISOR_fpu_taskswitch()) +#define stts() (HYPERVISOR_fpu_taskswitch(1)) #endif /* __KERNEL__ */ diff --git a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c index 207140ee60..017b167c38 100644 --- a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c +++ b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c @@ -500,7 +500,7 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas */ if (prev_p->thread_info->status & TS_USEDFPU) { __save_init_fpu(prev_p); /* _not_ save_init_fpu() */ - queue_multicall0(__HYPERVISOR_fpu_taskswitch); + queue_multicall1(__HYPERVISOR_fpu_taskswitch, 1); } /* diff --git a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/traps.c b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/traps.c index 54f014e605..49ce793c7b 100644 --- a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/traps.c +++ b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/traps.c @@ -902,14 +902,6 @@ asmlinkage void math_state_restore(struct pt_regs regs) struct thread_info *thread = current_thread_info(); struct task_struct *tsk = thread->task; - /* - * A trap in kernel mode can be ignored. It'll be the fast XOR or - * copying libraries, which will correctly save/restore state and - * reset the TS bit in CR0. - */ - if ((regs.xcs & 2) == 0) - return; - /* NB. 'clts' is done for us by Xen during virtual trap. */ if (!tsk->used_math) init_fpu(tsk); diff --git a/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/system.h b/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/system.h index 6e882483a6..77b6a507bd 100644 --- a/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/system.h +++ b/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/system.h @@ -106,17 +106,16 @@ static inline unsigned long _get_base(char * addr) /* * Clear and set 'TS' bit respectively */ -#define clts() __asm__ __volatile__ ("clts") +#define clts() (HYPERVISOR_fpu_taskswitch(0)) #define read_cr0() \ BUG(); #define write_cr0(x) \ BUG(); - #define read_cr4() \ BUG(); #define write_cr4(x) \ BUG(); -#define stts() (HYPERVISOR_fpu_taskswitch()) +#define stts() (HYPERVISOR_fpu_taskswitch(1)) #endif /* __KERNEL__ */ diff --git a/linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h b/linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h index 09a1bb7d83..b82db08f70 100644 --- a/linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h +++ b/linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h @@ -212,12 +212,16 @@ HYPERVISOR_set_callbacks( static inline int HYPERVISOR_fpu_taskswitch( - void) + int set) { int ret; + unsigned long ign; + __asm__ __volatile__ ( TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_fpu_taskswitch) : "memory" ); + : "=a" (ret), "=b" (ign) + : "0" (__HYPERVISOR_fpu_taskswitch), "1" (set) + : "memory" ); return ret; } diff --git a/netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c b/netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c index 5ec2d45271..ded4538782 100644 --- a/netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c @@ -412,7 +412,7 @@ i386_proc0_tss_ldt_init() ltr(lwp0.l_md.md_tss_sel); lldt(pcb->pcb_ldt_sel); #else - HYPERVISOR_fpu_taskswitch(); + HYPERVISOR_fpu_taskswitch(1); XENPRINTF(("lwp tss sp %p ss %04x/%04x\n", (void *)pcb->pcb_tss.tss_esp0, pcb->pcb_tss.tss_ss0, IDXSEL(pcb->pcb_tss.tss_ss0))); @@ -455,7 +455,7 @@ i386_switch_context(struct pcb *new) ci = curcpu(); if (ci->ci_fpused) { - HYPERVISOR_fpu_taskswitch(); + HYPERVISOR_fpu_taskswitch(1); ci->ci_fpused = 0; } diff --git a/netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h b/netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h index eb91c2a980..2ac01b4d25 100644 --- a/netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h @@ -180,12 +180,16 @@ HYPERVISOR_set_callbacks( } static inline int -HYPERVISOR_fpu_taskswitch(void) +HYPERVISOR_fpu_taskswitch(int set) { int ret; + unsigned long ign; + __asm__ __volatile__ ( TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_fpu_taskswitch) : "memory" ); + : "=a" (ret), "=b" (ign) + : "0" (__HYPERVISOR_fpu_taskswitch), "1" (set) + : "memory" ); return ret; } diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index fc4d464e08..422c737c43 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -348,6 +348,25 @@ asmlinkage int do_page_fault(struct xen_regs *regs) return 0; } +long do_fpu_taskswitch(int set) +{ + struct exec_domain *ed = current; + + if ( set ) + { + set_bit(EDF_GUEST_STTS, &ed->ed_flags); + stts(); + } + else + { + clear_bit(EDF_GUEST_STTS, &ed->ed_flags); + if ( test_bit(EDF_USEDFPU, &ed->ed_flags) ) + clts(); + } + + return 0; +} + static int emulate_privileged_op(struct xen_regs *regs) { extern void *decode_reg(struct xen_regs *regs, u8 b); @@ -369,9 +388,7 @@ static int emulate_privileged_op(struct xen_regs *regs) switch ( opcode ) { case 0x06: /* CLTS */ - clear_bit(EDF_GUEST_STTS, &ed->ed_flags); - if ( test_bit(EDF_USEDFPU, &ed->ed_flags) ) - clts(); + (void)do_fpu_taskswitch(0); break; case 0x09: /* WBINVD */ @@ -420,17 +437,7 @@ static int emulate_privileged_op(struct xen_regs *regs) switch ( (opcode >> 3) & 7 ) { case 0: /* Write CR0 */ - if ( *reg & X86_CR0_TS ) - { - set_bit(EDF_GUEST_STTS, &ed->ed_flags); - stts(); - } - else - { - clear_bit(EDF_GUEST_STTS, &ed->ed_flags); - if ( test_bit(EDF_USEDFPU, &ed->ed_flags) ) - clts(); - } + (void)do_fpu_taskswitch(!!(*reg & X86_CR0_TS)); break; case 2: /* Write CR2 */ @@ -827,14 +834,6 @@ long do_set_trap_table(trap_info_t *traps) } -long do_fpu_taskswitch(void) -{ - set_bit(EDF_GUEST_STTS, ¤t->ed_flags); - stts(); - return 0; -} - - #if defined(__i386__) #define DB_VALID_ADDR(_a) \ ((_a) <= (PAGE_OFFSET - 4)) -- 2.30.2